package view

import (
	"cloudops/src/common"
	"cloudops/src/config"
	"cloudops/src/models"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"go.uber.org/zap"
	"strconv"
	"strings"
	"time"
)

// 执行工单实例的结果
type actionWorkOrderInstanceOneResult struct {
	IsSuccess bool   `json:"isSuccess"  `
	Output    string `json:"output" validate:"required,min=1"`
}

// 创建工单
func createWorkOrderInstance(c *gin.Context) {

	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	var reqObj models.WorkOrderInstance
	err := c.ShouldBindJSON(&reqObj)
	if err != nil {
		sc.Logger.Error("解析新增工单实例请求失败", zap.Any("工单实例", reqObj), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 在这里校验字段，是否必填，范围是否正确
	err = validate.Struct(reqObj)
	if err != nil {
		if errors, ok := err.(validator.ValidationErrors); ok {
			common.ReqBadFailWithWithDetailed(
				gin.H{
					"翻译前": err.Error(),
					"翻译后": errors.Translate(trans),
				},
				"请求出错",
				c,
			)
			return
		}
		common.ReqBadFailWithMessage(err.Error(), c)
		return

	}
	// 校验传过来的 TemplateId
	_, err = models.GetWorkOrderTemplateById(int(reqObj.TemplateId))
	if err != nil {
		sc.Logger.Error("根据模板id找Template错误",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("根据模板id找Template错误:%v", err.Error()), c)
		return
	}

	userName := c.MustGet(common.GIN_CTX_JWT_USER_NAME).(string)
	dbUser, err := models.GetUserByUserName(userName)
	if err != nil {
		sc.Logger.Error("通过token解析到的userName去数据库中找User失败",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("通过token解析到的userName去数据库中找User失败:%v", err.Error()), c)
		return
	}

	reqObj.UserID = dbUser.ID

	// 创建工单
	err = reqObj.CreateOneWorkOrderInstance()
	if err != nil {
		sc.Logger.Error("新增工单实例数据库失败", zap.Any("工单实例", reqObj), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	common.OkWithMessage("创建成功", c)
}

// 获取工单详情
func getWorkOrderInstanceList(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 分页限制
	currentPage, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "100"))

	// 设置查询过滤条件
	searchUserID := c.DefaultQuery("UserID", "")
	searchUserIDInt, _ := strconv.Atoi(searchUserID)
	searchName := c.DefaultQuery("name", "")
	searchStatus := c.DefaultQuery("status", "")

	userName := c.MustGet(common.GIN_CTX_JWT_USER_NAME).(string)
	dbUser, err := models.GetUserByUserName(userName)
	if err != nil {
		sc.Logger.Error("通过token解析到的userName去数据库中找User失败",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("通过token解析到的userName去数据库中找User失败:%v", err.Error()), c)
		return
	}

	offset := 0
	limit := 0
	limit = pageSize
	if currentPage > 1 {
		offset = (currentPage - 1) * limit
	}

	var (
		objs  []*models.WorkOrderInstance
		total int
		count int64
	)
	isRelatedWithMe := false

	// 查询模式
	queryMode := c.DefaultQuery("queryMode", common.WorkOrderInstanceQueryModeCreate)
	if searchStatus != "" {
		// 根据状态查询，我们就把 查询模式变为all
		queryMode = common.WorkOrderInstanceQueryModeAll
	}

	switch queryMode {
	case common.WorkOrderInstanceQueryModeCreate:

		// 查询的第一种情况  最通用的 查询 我创建的
		objs, err = models.GetWorkOrderInstanceByCreateUserIdWithLimitOffset(dbUser.ID, limit, offset)
		if err != nil {
			errMsg := "获取当前用户创建的工单实例失败"
			sc.Logger.Error(errMsg,
				zap.Error(err),
			)
			common.ReqBadFailWithMessage(fmt.Sprintf("%v:%v", errMsg, err.Error()), c)
			return
		}
		total = models.GetWorkOrderInstanceCountByCreateUserId(dbUser.ID)
	// 查询所有
	case common.WorkOrderInstanceQueryModeAll:
		// 	数据库中拿到所有的menu列表
		objs, err = models.GetWorkOrderInstanceAll()
		if err != nil {
			sc.Logger.Error("去数据库中拿所有的工单实例错误",
				zap.Error(err),
			)
			common.ReqBadFailWithMessage(fmt.Sprintf("去数据库中拿所有的工单实例错误:%v", err.Error()), c)
			return
		}
		allIds := []int{}
		//// 遍历 role 准备menuIds 列表
		for _, obj := range objs {
			obj := obj

			// 在这里处理查询
			if searchName != "" && !strings.Contains(obj.Name, searchName) {
				continue
			}

			if searchStatus != "" && obj.Status != searchStatus {
				continue
			}

			// 在这里处理查询
			if searchUserID != "" && int(obj.UserID) != searchUserIDInt {
				continue
			}
			allIds = append(allIds, int(obj.ID))

			//role.MenuIds = menuIds
		}

		total = len(allIds)
		if len(allIds) == 0 {
			common.OkWithDetailed(allIds, "ok", c)
			return
		}

		objs, err = models.GetWorkOrderInstanceByIdsWithLimitOffset(allIds, limit, offset)
		if err != nil {
			sc.Logger.Error("limit-offset去数据库中拿所有的工单实例错误",
				zap.Error(err),
			)
			common.ReqBadFailWithMessage(fmt.Sprintf("limit-offset去数据库中拿所有的工单实例错误:%v", err.Error()), c)
			return
		}
	//  根据状态查询 待我审批的工单
	case common.WorkOrderInstanceQueryModeApproval:
		isRelatedWithMe = true
		// 查询条件
		// 状态得是待审批的
		// 把userName 或者RoleName 给传进去 查询 CurrentFlowNode是  用户@user  组@role
		currentFlowNodes := []string{
			fmt.Sprintf("用户@%s", dbUser.Username),
		}
		for _, role := range dbUser.Roles {
			role := role
			currentFlowNodes = append(currentFlowNodes, fmt.Sprintf("组@%s", role.RoleValue))
		}

		objs, count, err = models.GetWorkOrderInstanceByStatusAndCurrentFlowNodesWithLimitOffset(
			common.WorkOrderInstanceStatusPendingApproval,
			currentFlowNodes,
			limit,
			offset,
		)
		total = int(count)
	// 根据状态查询 待执行的工单
	case common.WorkOrderInstanceQueryModeAction:
		isRelatedWithMe = true
		currentFlowNodes := []string{
			fmt.Sprintf("用户@%s", dbUser.Username),
		}

		for _, role := range dbUser.Roles {
			role := role
			currentFlowNodes = append(currentFlowNodes, fmt.Sprintf("组@%s", role.RoleValue))
		}

		objs, count, err = models.GetWorkOrderInstanceByStatusAndCurrentFlowNodesWithLimitOffset(
			common.WorkOrderInstanceStatusPendingAction,
			currentFlowNodes,
			limit,
			offset,
		)
		total = int(count)
	}

	for _, obj := range objs {
		obj := obj
		obj.IsRelatedWithMe = isRelatedWithMe
		obj.FillFrontAllDataWorkOrderInstance()
	}

	resp := &ResponseResourceCommon{
		Total: total,
		Items: objs,
	}
	common.OkWithDetailed(resp, "ok", c)
}

// 工单审批和通知
func approvalWorkOrderInstance(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	// 获取操作人
	userName := c.MustGet(common.GIN_CTX_JWT_USER_NAME).(string)
	dbUser, err := models.GetUserByUserName(userName)
	if err != nil {
		sc.Logger.Error("通过token解析到的userName去数据库中找User失败",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("通过token解析到的userName去数据库中找User失败:%v", err.Error()), c)
		return
	}
	// 执行审批的操作
	approvalAction := c.Query("approvalAction")
	if _, ok := common.ApprovalActionMap[approvalAction]; !ok {
		common.ReqBadFailWithMessage("审批动作传参错误或没传", c)
		return
	}

	id := c.Param("id")
	isPass := true
	outPut := ""

	// 先去db中根据id找到这个工单
	intVar, _ := strconv.Atoi(id)
	dbObj, err := models.GetWorkOrderInstanceById(intVar)
	if err != nil {
		sc.Logger.Error("根据id找工单实例错误", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 记录工单的审批状态，以及审批意见，审批人
	var flowNodes []models.FlowNode
	err = json.Unmarshal([]byte(dbObj.ActualFlowData), &flowNodes)
	if err != nil {
		sc.Logger.Error("json获取之前的审批记录", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}
	sc.Logger.Info("获取当前审批状态",
		zap.Any("审批类型", approvalAction),
		zap.Any("审批人", dbUser.RealName),
		zap.Any("flowNodes", flowNodes),
	)
	// 审批人或者执行工单的执行人
	approvalNodes := []models.FlowNode{}
	actionNodes := []models.FlowNode{}

	thisNodeIndex := 0
	thisNodeIndexFound := false
	for index, flowNode := range flowNodes {
		if flowNode.ActualUser == "" && thisNodeIndexFound == false {
			thisNodeIndex = index
			// 只能赋值一次
			thisNodeIndexFound = true
		}
		switch flowNode.Type {
		case common.FLOW_TYPE_Approval:
			approvalNodes = append(approvalNodes, flowNode)
		case common.FLOW_TYPE_Action:
			actionNodes = append(actionNodes, flowNode)

		}

	}
	// 计算已完成审批的节点数量
	alreadyApprovalNum := 0
	for i := 0; i < len(approvalNodes); i++ {
		node := approvalNodes[i]
		if node.ActualUser != "" {
			alreadyApprovalNum++
		}
	}
	// 调整状态
	switch approvalAction {
	case common.ApprovalActionPass:
		isPass = true
		outPut = "审批通过"
		// 算上本次的审批然后全部审批完了，说明 已完成审批，状态需要变成 待执行
		if alreadyApprovalNum+1 == len(approvalNodes) {
			dbObj.Status = common.WorkOrderInstanceStatusPendingAction
		}
	case common.ApprovalActionReject:
		isPass = false
		outPut = "审批拒绝"
		dbObj.Status = common.WorkOrderInstanceStatusApprovalReject

	}
	// 调整下一个处理人
	// 非最后一个节点才需要调整
	if thisNodeIndex+1 < len(flowNodes) {
		// 当审批拒绝的时候下一个就不需要再设置了
		if approvalAction == common.ApprovalActionPass {
			dbObj.CurrentFlowNode = flowNodes[thisNodeIndex+1].DefineUserOrGroup
		}
	}
	// 更新下一个处理人为 我的下一个审批人
	// 设置 我认领处理了这个工单，在这个节点上
	flowNodes[thisNodeIndex].ActualUser = dbUser.Username
	flowNodes[thisNodeIndex].EndTime = time.Now().Format("2006-01-02 15:04:05")
	flowNodes[thisNodeIndex].IsPassOrIsSuccess = isPass
	flowNodes[thisNodeIndex].OutPut = outPut

	flowNodeStr, _ := json.Marshal(flowNodes)
	dbObj.ActualFlowData = string(flowNodeStr)
	err = dbObj.UpdateOneWorkOrderInstance()
	if err != nil {
		sc.Logger.Error("更新审批记录错误", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}
	common.OkWithMessage("认领并审批成功", c)

	// 当执行后通过钉钉推送消息
	createUser, err := models.GetUserById(int(dbObj.UserID))
	if err != nil {
		sc.Logger.Error("根据工单创建人id找用户失败", zap.Any("工单实例", id), zap.Error(err))
		common.ReqBadFailWithWithDetailed(fmt.Sprintf("根据工单创建人id找用户失败:%v", err.Error()), "获取创建人信息出错", c)
		return
	}

	// 工单的详情链接拼接
	detailUrl := fmt.Sprintf("%s%s%d",
		sc.Domain,
		sc.WorkOrderAutoActionC.DetailUrl,
		dbObj.ID,
	)

	// 拼接通知消息
	notifyMsg := fmt.Sprintf("工单通知：\n"+
		"@%v，您的工单 \"%v\" 已于 %v 被用户 @%v %v。\n"+
		"查看工单详情请点击链接：%v",
		// 用户名前加上 @ 符号
		createUser.RealName,                      // 工单创建用户的真实姓名
		dbObj.Name,                               // 工单名称
		time.Now().Format("2006-01-02 15:04:05"), // 当前时间
		dbUser.RealName,                          // 审批用户的真实姓名，前面加 @
		outPut,                                   // 工单操作结果，例如审批通过、驳回等
		detailUrl,                                // 工单详情链接
	)

	imc := sc.ImDingDingC
	imc.AtMobiles = []string{createUser.Mobile}
	//imc.Title = "工单执行通知"
	common.DingDingMsgDirectSend(imc, notifyMsg)
}

// 获取工单的当前审批状态
func getWorkOrderInstanceOne(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	id := c.Param("id")

	// 获取工单
	intVar, _ := strconv.Atoi(id)
	dbObj, err := models.GetWorkOrderInstanceById(intVar)
	if err != nil {
		sc.Logger.Error("根据id找工单实例错误", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}
	isRelatedWithMe := false
	// 判断是否关联当前审批人,或者组
	userName := c.MustGet(common.GIN_CTX_JWT_USER_NAME).(string)
	dbUser, err := models.GetUserByUserName(userName)
	if err != nil {
		sc.Logger.Error("通过token解析到的userName去数据库中找User失败",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("通过token解析到的userName去数据库中找User失败:%v", err.Error()), c)
		return
	}

	for _, role := range dbUser.Roles {
		role := role
		if fmt.Sprintf("组@%s", role.RoleValue) == dbObj.CurrentFlowNode {
			isRelatedWithMe = true
			break
		}
	}
	if dbObj.CurrentFlowNode == fmt.Sprintf("用户@%s", dbUser.Username) {
		isRelatedWithMe = true
	}
	dbObj.IsRelatedWithMe = isRelatedWithMe
	dbObj.FillFrontAllDataWorkOrderInstance()
	common.OkWithData(dbObj, c)
}

// 工单描述评论
func commentWorkOrderInstance(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	userName := c.MustGet(common.GIN_CTX_JWT_USER_NAME).(string)
	dbUser, err := models.GetUserByUserName(userName)
	if err != nil {
		sc.Logger.Error("通过token解析到的userName去数据库中找User失败",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("通过token解析到的userName去数据库中找User失败:%v", err.Error()), c)
		return
	}

	id := c.Param("id")
	// 先去db中根据id找到这个工单实例
	intVar, _ := strconv.Atoi(id)
	dbObj, err := models.GetWorkOrderInstanceById(intVar)
	if err != nil {
		sc.Logger.Error("根据id找工单实例错误", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	var reqObj models.WorkOrderInstanceComment
	err = c.ShouldBindJSON(&reqObj)
	if err != nil {
		sc.Logger.Error("解析工单更新结果请求失败", zap.Any("工单结果", reqObj), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 在这里校验字段，是否必填，范围是否正确
	err = validate.Struct(reqObj)
	if err != nil {
		if errors, ok := err.(validator.ValidationErrors); ok {
			common.ReqBadFailWithWithDetailed(
				gin.H{
					"翻译前": err.Error(),
					"翻译后": errors.Translate(trans),
				},
				"请求出错",
				c,
			)
			return
		}
		common.ReqBadFailWithMessage(err.Error(), c)
		return

	}

	// 获取之前的评论记录
	comments := []models.WorkOrderInstanceComment{}
	if dbObj.Comments != "" {
		err = json.Unmarshal([]byte(dbObj.Comments), &comments)
		if err != nil {
			sc.Logger.Error("json获取之前的评论记录", zap.Any("工单实例", id), zap.Error(err))
			common.FailWithMessage(err.Error(), c)
			return
		}
	}

	reqObj.UserNameTime = fmt.Sprintf("%s %s", time.Now().Format("2006-01-02 15:04:05"), dbUser.Username)
	comments = append(comments, reqObj)
	commonStr, _ := json.Marshal(comments)
	dbObj.Comments = string(commonStr)
	err = dbObj.UpdateOneWorkOrderInstance()
	if err != nil {
		sc.Logger.Error("更新评论记录错误", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}
	common.OkWithMessage("评论成功", c)
}

// 工单执行记录
func actionWorkOrderInstance(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	userName := c.MustGet(common.GIN_CTX_JWT_USER_NAME).(string)
	dbUser, err := models.GetUserByUserName(userName)
	if err != nil {
		sc.Logger.Error("通过token解析到的userName去数据库中找User失败",
			zap.Error(err),
		)
		common.ReqBadFailWithMessage(fmt.Sprintf("通过token解析到的userName去数据库中找User失败:%v", err.Error()), c)
		return
	}
	id := c.Param("id")
	intVar, _ := strconv.Atoi(id)
	dbObj, err := models.GetWorkOrderInstanceById(intVar)
	if err != nil {
		sc.Logger.Error("根据id找工单实例错误", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	var reqObj actionWorkOrderInstanceOneResult
	err = c.ShouldBindJSON(&reqObj)
	if err != nil {
		sc.Logger.Error("解析工单更新结果请求失败", zap.Any("工单结果", reqObj), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 在这里校验字段，是否必填，范围是否正确
	err = validate.Struct(reqObj)
	if err != nil {
		if errors, ok := err.(validator.ValidationErrors); ok {
			common.ReqBadFailWithWithDetailed(
				gin.H{
					"翻译前": err.Error(),
					"翻译后": errors.Translate(trans),
				},
				"请求出错",
				c,
			)
			return
		}
		common.ReqBadFailWithMessage(err.Error(), c)
		return

	}

	var flowNodes []models.FlowNode
	err = json.Unmarshal([]byte(dbObj.ActualFlowData), &flowNodes)
	if err != nil {
		sc.Logger.Error("json获取之前的审批记录", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	actionNodes := []models.FlowNode{}
	thisNodeIndex := 0
	thisNodeIndexFound := false
	for index, flowNode := range flowNodes {
		if flowNode.ActualUser == "" && thisNodeIndexFound == false {
			thisNodeIndex = index
			// 只能赋值一次
			thisNodeIndexFound = true
		}
		switch flowNode.Type {
		case common.FLOW_TYPE_Action:
			actionNodes = append(actionNodes, flowNode)
		}
	}
	// 计算已完成执行的节点数量
	alreadyActionNum := 0
	for i := 0; i < len(actionNodes); i++ {
		node := actionNodes[i]
		if node.ActualUser != "" {
			alreadyActionNum++
		}
	}

	// 调整状态
	if alreadyActionNum+1 == len(actionNodes) {
		dbObj.Status = common.WorkOrderInstanceStatusFinished
	}
	// 调整下一个处理人
	// 非最后一个节点才需要调整
	if thisNodeIndex+1 < len(flowNodes) {
		// 更新下一个处理人为 我的下一个
		dbObj.CurrentFlowNode = flowNodes[thisNodeIndex+1].DefineUserOrGroup
	}

	// 当审批拒绝的时候下一个就不需要再设置了
	// 设置 我认领处理了这个工单，在这个节点上
	flowNodes[thisNodeIndex].ActualUser = dbUser.Username
	flowNodes[thisNodeIndex].OutPut = reqObj.Output
	flowNodes[thisNodeIndex].IsPassOrIsSuccess = reqObj.IsSuccess
	flowNodes[thisNodeIndex].EndTime = time.Now().Format("2006-01-02 15:04:05")
	flowNodeStr, _ := json.Marshal(flowNodes)
	dbObj.ActualFlowData = string(flowNodeStr)
	err = dbObj.UpdateOneWorkOrderInstance()
	if err != nil {
		sc.Logger.Error("更新执行记录错误", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}
	common.OkWithMessage("认领并执行成功", c)

	// 当执行后通过钉钉推送消息
	createUser, err := models.GetUserById(int(dbObj.UserID))
	if err != nil {
		sc.Logger.Error("根据工单创建人id找用户失败", zap.Any("工单实例", id), zap.Error(err))
		common.ReqBadFailWithWithDetailed(fmt.Sprintf("根据工单创建人id找用户失败:%v", err.Error()), "获取创建人信息出错", c)
		return
	}

	// 工单的详情链接拼接
	detailUrl := fmt.Sprintf("%s%s%d",
		sc.Domain,
		sc.WorkOrderAutoActionC.DetailUrl,
		dbObj.ID,
	)

	// 拼接通知消息
	notifyMsg := fmt.Sprintf("工单通知：\n"+
		"@%v，您的工单 \"%v\" 已于 %v 被用户 @%v %v。\n"+
		"查看工单详情请点击链接：%v",
		// 用户名前加上 @ 符号
		createUser.RealName,                      // 工单创建用户的真实姓名
		dbObj.Name,                               // 工单名称
		time.Now().Format("2006-01-02 15:04:05"), // 当前时间
		dbUser.RealName,                          // 审批用户的真实姓名，前面加 @
		reqObj.Output,                            // 工单操作结果，例如审批通过、驳回等
		detailUrl,                                // 工单详情链接
	)

	imc := sc.ImDingDingC
	imc.AtMobiles = []string{createUser.Mobile}
	//imc.Title = "工单执行通知"
	common.DingDingMsgDirectSend(imc, notifyMsg)
}

// 催单操作
func urgeWorkOrderInstance(c *gin.Context) {
	sc := c.MustGet(common.GIN_CTX_CONFIG_CONFIG).(*config.ServerConfig)
	userName := c.MustGet(common.GIN_CTX_JWT_USER_NAME).(string)

	// 获取催单用户的信息
	dbUser, err := models.GetUserByUserName(userName)
	if err != nil {
		sc.Logger.Error("无法根据用户名获取用户信息",
			zap.String("userName", userName), // 输出失败的用户名
			zap.Error(err),
		)
		common.ReqBadFailWithMessage("无法获取用户信息，请检查用户名或权限", c)
		return
	}

	// 只输出必要的信息，避免泄露敏感数据
	sc.Logger.Info("催单用户信息",
		zap.Any("userID", dbUser.ID),            // 获取用户的ID
		zap.String("userName", dbUser.Username), // 只输出用户名
	)

	// 获取工单实例
	id := c.Param("id")
	intVar, _ := strconv.Atoi(id)
	dbObj, err := models.GetWorkOrderInstanceById(intVar)
	if err != nil {
		sc.Logger.Error("根据id找工单实例错误", zap.Any("工单实例", id), zap.Error(err))
		common.FailWithMessage(err.Error(), c)
		return
	}

	// 获取当前审批人
	currentFlowNode := dbObj.CurrentFlowNode
	if currentFlowNode == "" {
		common.ReqBadFailWithMessage("工单当前没有审批人", c)
		return
	}

	// 判断当前审批人是用户还是组
	var currentUserOrGroup string
	if strings.HasPrefix(currentFlowNode, "用户@") {
		currentUserOrGroup = strings.TrimPrefix(currentFlowNode, "用户@")
	} else if strings.HasPrefix(currentFlowNode, "组@") {
		currentUserOrGroup = strings.TrimPrefix(currentFlowNode, "组@")
	} else {
		common.ReqBadFailWithMessage("无法识别当前审批人", c)
		return
	}

	// 查询审批人信息
	var targetUser *models.User
	if strings.HasPrefix(currentFlowNode, "用户@") {
		targetUser, err = models.GetUserByUserName(currentUserOrGroup)
		if err != nil {
			sc.Logger.Error("通过当前审批人找User失败", zap.Error(err))
			common.FailWithMessage("找不到当前审批人信息", c)
			return
		}
	}

	// 发送催单通知
	notifyMsg := fmt.Sprintf("催单通知：\n"+
		"@%v，工单 \"%v\" 需要您的尽快处理。\n"+
		"期望完成时间：%v\n"+
		"查看工单详情请点击链接：%v",
		// 当前审批人名前加上 @ 符号
		currentUserOrGroup,     // 当前审批人
		dbObj.Name,             // 工单名称
		dbObj.DesireFinishTime, // 期望完成时间
		fmt.Sprintf("%s%s%d", sc.Domain, sc.WorkOrderAutoActionC.DetailUrl, dbObj.ID), // 工单详情链接
	)

	// 通过钉钉催促当前审批人
	imc := sc.ImDingDingC
	imc.AtMobiles = []string{targetUser.Mobile}
	common.DingDingMsgDirectSend(imc, notifyMsg)

	// 返回催单成功消息
	common.OkWithMessage("催单通知已发送", c)
}
